/**
 * author:Administrator
 * date:2016/2/25
 * desc:TODO 如果Ware发生变化,是否传播到 order
 */

'use strict';
let FormatDate = require('../../../infrastructure/appUtil/FormatDate.js');
let Repo = require('./OrderRepo.js');
let DomainModel = require('../../../lib/DomainModel.js');
let events = require('../../saga/domainEvent.js');

let STATUS_ENUM = {
  placed: 'placed',               //0,    // 等待系统确认(start)
  created: 'created',             //1,    // 等待系统确认(start)
  recall: 'recall',               //2,    // 取消订单,存货不足(end)

  paid: 'paid',                   //3,    // 已支付(end)
  cancelled: 'cancelled',         //4     // 取消(end)
};

class Order extends DomainModel {
  constructor() {
    super();
  }

  /**
   * 新建 一个当前对象的实例
   * @param pojo, key:
   */
  static freshNew(pojo) {
    let order = new Order();
    order.customerId = pojo.customerId;
    order.vendorId = pojo.vendorId;
    order.snapshotId = pojo.snapshotId;
    order.wareId = pojo.wareId;
    order.wareCount = pojo.wareCount;

    //
    order.totalMoney = Order.calMoney(pojo.price, pojo.wareCount);
    order.money = order.totalMoney;
    order.status = STATUS_ENUM.placed;
    order.createdAt = FormatDate.unixTimestamp();
    order.updatedAt = FormatDate.unixTimestamp();
    order.payAt = null;
    order.couponLogId = null;// 优惠券
    return order;
  }

  /**
   * 从数据库中读取，re-constructor an obj
   * @param pojo
   */
  static rebuild(pojo) {
    let item = new Order();
    let keys = Object.keys(pojo);
    for (let key of keys) {
      item[key] = pojo[key];
    }
    return item;
  }


  /**
   * 计算订单 总款项
   * @param singlePrice
   * @param count
   * @returns {number}
   */
  static calMoney(singlePrice, count) {
    return singlePrice * count;
  }

  /**
   * 使用一个优惠券
   * TODO 如果order存在并发修改，这种更新方法是不行的
   * @param couponLog 优惠券领取记录
   */
  * attachCoupon(couponLog, sagaId) {
    let where = {id: this.id, status: STATUS_ENUM.created, couponLogId: null};
    let updateAttr = {couponLogId: couponLog.id, money: this.money - couponLog.money};
    let isOk = yield Repo.update(where, updateAttr);
    isOk = isOk[0];
    if (!isOk) {
      this.pubDomainEvent(new events.AttchCouponFail(sagaId, couponLog));
    }
    return isOk;
  }

  * store(sagaId) {
    let isNew = !this.id;
    yield Repo.store(this);
    if (isNew) {
      this.pubDomainEvent(new events.OrderPlaced(sagaId, this));
    }
  }

  * whenWareReserved(sagaId) {
    let where = {id: this.id, status: STATUS_ENUM.placed};
    let updateAttr = {status: STATUS_ENUM.created};
    yield Repo.update(where, updateAttr);
    this.pubDomainEvent(new events.OrderCreated(sagaId, this));
  }

  * whenWareLacking(sagaId) {
    let where = {id: this.id, status: STATUS_ENUM.placed};
    let updateAttr = {status: STATUS_ENUM.recall};
    yield Repo.update(where, updateAttr);
    this.pubDomainEvent(new events.OrderRecall(sagaId, this));
  }

  canPay() {
    return this.status == STATUS_ENUM.created;
  }

  /** 进行支付 */
  * pay(sagaId) {
    let where = {id: this.id, status: STATUS_ENUM.created};
    let updateAttr = {status: STATUS_ENUM.paid};
    let isOk = yield Repo.update(where, updateAttr);
    if (isOk) {
      this.pubDomainEvent(new events.OrderPaid(sagaId, this));
    }
  }

}

Order.STATUS_ENUM = STATUS_ENUM;
module.exports = Order;
